﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Moonlite.ExtensionApi.XimlInterfaces;

namespace Moonlite.Platform.Ximl {
    public sealed class ObjectManager : IObjectManager {
        private Dictionary<KeyValuePair<Assembly, Guid>, IObject> objects = new Dictionary<KeyValuePair<Assembly, Guid>, IObject>();
        public IObject GetObject(Guid guid, Assembly owner) {
            foreach (KeyValuePair<Assembly, Guid> identifiers in objects.Keys) {
                if (identifiers.Key == owner && identifiers.Value == guid) {
                    return objects[identifiers];
                }
            }
            return null;
        }
        public IObject CreateObject(DescriptorBase descriptor, Assembly owner, Type desiredType) {
            Type objectType = typeof(IObject);
            if (desiredType != objectType) {
                bool inheritsIObject = false;
                foreach (Type interfaceType in desiredType.GetInterfaces()) {
                    if (interfaceType == objectType) {
                        inheritsIObject = true;
                        break;
                    }
                }
                if (!inheritsIObject) {
                    throw new ArgumentException("desiredType must inherit IObject.");
                }
                const string CreateMethodName = "Create";
                Assembly thisAssembly = typeof(ObjectManager).Assembly;
                Assembly extensionAssembly = typeof(IObjectManager).Assembly;
                List<Type> types = thisAssembly.GetTypes().ToList();
                types.AddRange(extensionAssembly.GetTypes().ToList());
                foreach (Type type in types) {
                    if (type == desiredType) {
                        // Substring(1) cuts off the I of the I(X)Object. The interface must be placed in ExtensionApi.dll and the implemention in Moonlite.Platform.Ximl.dll.
                        object @object = Activator.CreateInstance(thisAssembly.GetType("Moonlite.Platform.Ximl." + type.Name.Substring(1)));
                        MethodInfo info = @object.GetType().GetMethod(CreateMethodName);
                        info.Invoke(@object, new object[] { descriptor });
                        KeyValuePair<Assembly, Guid> key = new KeyValuePair<Assembly, Guid>(owner, descriptor.Guid);
                        if (!objects.ContainsKey(key)) {
                            objects.Add(key, (IObject)@object);
                        }
                        return (IObject)@object;
                    }
                }
            }
            return null;
        }
    }
}
